import FullScreenModal from '@/components/Common/fullScreen';
import OpenFileDialog from '@/components/OpenFileDialog';
import FormView from '@/executor/open/form';
import { model, schema } from '@/ts/base';
import { deepClone } from '@/ts/base/common';
import { IBelong, IFinancial, TargetType, IPeriod } from '@/ts/core';
import { Form, IForm } from '@/ts/core/thing/standard/form';
import { ProTable } from '@ant-design/pro-components';
import { Button, Card, DatePicker, Empty, Space, Spin, Tag } from 'antd';
import React, { ReactNode, useEffect, useRef, useState } from 'react';
import Depreciation from './depreciation';
import { DepreciationTemplate } from './depreciation/template';
import Ledger from './ledger/ledger';
import { Closing } from './closing';
import { CloseOutlined } from '@ant-design/icons';
import PrimaryForms from '@/executor/tools/workForm/primary';
import orgCtrl from '@/ts/controller';
import { formatDate } from '@/utils';

interface IProps {
  financial: IFinancial;
}

const Financial: React.FC<IProps> = ({ financial }) => {
  const [metadata, setMetadata] = useState(financial.metadata);
  const month = useRef<string>();
  useEffect(() => {
    const id = financial.subscribe(() => setMetadata({ ...financial.metadata }));
    return () => financial.unsubscribe(id);
  }, []);
  const Center = () => {
    const [loading, setLoading] = useState(false);
    if (metadata?.initialized) {
      return (
        <Space>
          <Card>{'初始结账日期：' + (metadata.initialized ?? '')}</Card>
          <Card>{'当前业务账期：' + (metadata?.current ?? '')}</Card>
          {metadata?.initialized && !financial.current && (
            <Button
              loading={loading}
              onClick={async () => {
                setLoading(true);
                await financial.createSnapshots(metadata.initialized!);
                const next = financial.getOffsetPeriod(metadata.initialized!, 1);
                await financial.createPeriod(next);
                setLoading(false);
              }}>
              生成期初账期
            </Button>
          )}
          <Button onClick={() => financial.clear()}>清空初始化</Button>
        </Space>
      );
    } else {
      return (
        <Space>
          <DatePicker
            style={{ width: '100%' }}
            picker="month"
            onChange={(_, data) => (month.current = data)}
          />
          <Button
            onClick={async () => {
              if (month.current) {
                financial.setInitialize(month.current);
              }
            }}>
            确认
          </Button>
        </Space>
      );
    }
  };
  return (
    <Card
      title={
        <Space>
          {'初始化账期'}
          {metadata?.initialized ? (
            <Tag color="green">已初始化</Tag>
          ) : (
            <Tag color="red">未初始化</Tag>
          )}
        </Space>
      }>
      {<Center />}
    </Card>
  );
};

export interface FullProps {
  title: string;
  onFinished?: () => void;
  onCancel?: () => void;
  onSave?: () => void;
  children: ReactNode;
}

export const FullScreen: React.FC<FullProps> = (props) => {
  return (
    <FullScreenModal
      open
      centered
      fullScreen
      destroyOnClose
      width={'80vw'}
      bodyHeight={'80vh'}
      title={props.title}
      onOk={props.onFinished}
      onCancel={props.onCancel}
      onSave={props.onSave}>
      {props.children}
    </FullScreenModal>
  );
};

const Periods: React.FC<IProps> = ({ financial }) => {
  const [periods, setPeriods] = useState<IPeriod[]>([]);
  const [form, setForm] = useState(financial.form);
  const [balance, setBalance] = useState(financial.balance);
  const [center, setCenter] = useState(<></>);
  useEffect(() => {
    const id = financial.subscribe(async () => {
      setPeriods([...(await financial.loadPeriods())]);
      setForm(await financial.loadForm());
      setBalance(await financial.loadBalance());
    });
    return () => financial.unsubscribe(id);
  }, []);
  const binding = (type: string) => {
    setCenter(
      <OpenFileDialog
        accepts={['表单']}
        rootKey={financial.space.directory.key}
        onOk={async (files) => {
          if (files.length > 0) {
            const metadata = files[0].metadata as schema.XForm;
            switch (type) {
              case 'form':
                await financial.setForm(metadata);
                break;
              case 'balance':
                await financial.setBalance(metadata);
                break;
            }
          }
          setCenter(<></>);
        }}
        onCancel={() => setCenter(<></>)}
      />,
    );
  };
  return (
    <>
      <Card title={'结账记录'}>
        <ProTable<IPeriod>
          search={false}
          options={false}
          pagination={{ pageSize: 10 }}
          dataSource={periods}
          columns={[
            {
              title: '序号',
              valueType: 'index',
            },
            {
              title: '期间',
              valueType: 'text',
              dataIndex: 'period',
            },
            {
              title: '是否已折旧',
              valueType: 'text',
              dataIndex: 'deprecated',
              render(_, entity) {
                if (entity.deprecated) {
                  return <Tag color="green">已折旧</Tag>;
                }
                return <Tag color="red">未折旧</Tag>;
              },
            },
            {
              title: '是否已结账',
              valueType: 'text',
              dataIndex: 'closed',
              render(_, entity) {
                if (entity.closed) {
                  return <Tag color="green">已结账</Tag>;
                }
                return <Tag color="red">未结账</Tag>;
              },
            },
            {
              title: (
                <Space>
                  <span>资产负债表</span>
                  {balance && (
                    <Tag
                      color="green"
                      icon={
                        <CloseOutlined
                          onClick={() => {
                            financial.setBalance(undefined);
                          }}
                        />
                      }>
                      {balance.name}
                    </Tag>
                  )}
                </Space>
              ),
              valueType: 'text',
              render(_, item) {
                return (
                  <a
                    onClick={async () => {
                      if (!balance) {
                        binding('balance');
                      } else {
                        setCenter(
                          <BalanceSheet
                            period={item}
                            balance={balance}
                            onFinished={() => setCenter(<></>)}
                            onSave={() => setCenter(<></>)}
                            onCancel={() => setCenter(<></>)}
                            allowEdit={false}
                          />,
                        );
                      }
                    }}>
                    查看
                  </a>
                );
              },
            },
            {
              title: (
                <Space>
                  <span>快照</span>
                  {form && (
                    <Tag
                      color="green"
                      icon={
                        <CloseOutlined
                          onClick={() => {
                            financial.setForm(undefined);
                          }}
                        />
                      }>
                      {form.name}
                    </Tag>
                  )}
                </Space>
              ),
              valueType: 'text',
              render(_, item) {
                return (
                  <Space>
                    <a
                      onClick={() => {
                        if (!form) {
                          binding('form');
                        } else {
                          const metadata = deepClone(form.metadata);
                          metadata.collName = '_system-things_' + item.period;
                          setCenter(
                            <FormView
                              form={new Form(metadata, financial.space.directory)}
                              finished={() => setCenter(<></>)}
                            />,
                          );
                        }
                      }}>
                      查看
                    </a>
                  </Space>
                );
              },
            },
            {
              title: '总账',
              valueType: 'text',
              render(_, entity) {
                return (
                  <a
                    onClick={() => {
                      setCenter(
                        <FullScreen
                          title={entity.period + ' 资产总账'}
                          onFinished={() => setCenter(<></>)}
                          onCancel={() => setCenter(<></>)}>
                          <Ledger financial={financial} period={entity} />
                        </FullScreen>,
                      );
                    }}>
                    查看
                  </a>
                );
              },
            },
            {
              title: '操作',
              valueType: 'option',
              width: 300,
              render: (_, item) => {
                return (
                  <Space>
                    {!item.closed && (
                      <Button
                        type="primary"
                        size="small"
                        onClick={async () => {
                          const start = () => {
                            setCenter(
                              <FullScreen
                                title={'资产折旧'}
                                onFinished={() => setCenter(<></>)}
                                onCancel={() => setCenter(<></>)}>
                                <Depreciation
                                  financial={financial}
                                  current={item}
                                  config={financial.configuration.metadata!}
                                />
                              </FullScreen>,
                            );
                          };
                          try {
                            financial.configuration.checkConfig();
                            start();
                          } catch (e) {
                            setCenter(
                              <DepreciationTemplate
                                financial={financial}
                                onCancel={() => setCenter(<></>)}
                                onSaved={() => start()}
                              />,
                            );
                          }
                        }}>
                        发起折旧
                      </Button>
                    )}
                    {!item.closed && (
                      <Button
                        type="primary"
                        size="small"
                        onClick={async () => {
                          if (!balance) {
                            binding('balance');
                          } else {
                            setCenter(
                              <BalanceSheet
                                period={item}
                                balance={balance}
                                onFinished={() => setCenter(<></>)}
                                onSave={() => setCenter(<></>)}
                                onCancel={() => setCenter(<></>)}
                                allowEdit={true}
                              />,
                            );
                          }
                        }}>
                        加载财务数据
                      </Button>
                    )}
                    {!item.closed && (
                      <Button
                        type="primary"
                        size="small"
                        onClick={async () =>
                          setCenter(
                            <FullScreen
                              title={'月结账'}
                              onFinished={() => setCenter(<></>)}
                              onCancel={() => setCenter(<></>)}>
                              <Closing financial={financial} current={item} />
                            </FullScreen>,
                          )
                        }>
                        发起结账
                      </Button>
                    )}
                  </Space>
                );
              },
            },
          ]}
        />
      </Card>
      {center}
    </>
  );
};

interface FinancialProps {
  belong: IBelong;
}

const BelongFinancial: React.FC<FinancialProps> = ({ belong }) => {
  if ([TargetType.Company, TargetType.Person].includes(belong.typeName as TargetType)) {
    return (
      <Space style={{ width: '100%' }} direction="vertical">
        <Financial financial={belong.financial} />
        <Periods financial={belong.financial} />
      </Space>
    );
  }
  return <></>;
};

interface BalanceProps {
  period: IPeriod;
  balance: IForm;
  allowEdit: boolean;
  onFinished: () => void;
  onSave: () => void;
  onCancel: () => void;
}

const BalanceSheet: React.FC<BalanceProps> = (props) => {
  const [loading, setLoading] = useState(false);
  const [fields, setFields] = useState<model.FieldModel[]>([]);
  const balanceRef = useRef<schema.XThing>();

  const initializing = async () => {
    setLoading(true);
    const fields = deepClone(await props.balance.loadFields());
    setFields(fields);
    balanceRef.current = await props.period.loadBalance();
    if (balanceRef.current) {
      for (const field of fields) {
        balanceRef.current[field.id] = balanceRef.current[field.code];
        delete balanceRef.current[field.code];
      }
    }
    setLoading(false);
  };

  useEffect(() => {
    initializing();
  }, []);

  if (loading) {
    return (
      <FullScreen
        title={'资产负债表'}
        onFinished={props.onFinished}
        onCancel={props.onCancel}>
        <Spin spinning={loading}>
          <Empty>正在加载配置中</Empty>
        </Spin>
      </FullScreen>
    );
  }

  return (
    <FullScreen
      title={'资产负债表'}
      onFinished={props.onFinished}
      onCancel={props.onCancel}
      onSave={async () => {
        if (balanceRef.current) {
          balanceRef.current['period'] = props.period.period;
          for (const field of fields) {
            balanceRef.current[field.code] = balanceRef.current[field.id];
            delete balanceRef.current[field.id];
          }
          await props.period.balanceColl.replace(balanceRef.current);
        }
        props.onSave();
      }}>
      <PrimaryForms
        forms={[props.balance.metadata]}
        allowEdit={props.allowEdit}
        belong={props.period.space}
        infos={[
          {
            id: props.balance.id,
            typeName: '表单',
            allowAdd: true,
            allowEdit: true,
            allowSelect: false,
          },
        ]}
        changedFields={[]}
        data={{
          node: {} as model.WorkNodeModel,
          fields: { [props.balance.id]: fields },
          data: {},
          primary: {},
          rules: [],
        }}
        getFormData={(form) => {
          const after: schema.XThing[] = [];
          if (balanceRef.current) {
            after.push(balanceRef.current);
          }
          return {
            before: [],
            after: after,
            nodeId: '',
            creator: orgCtrl.user.id,
            formName: form.name,
            createTime: formatDate(new Date(), 'yyyy-MM-dd hh:mm:ss.S'),
            rules: [],
          };
        }}
        onChanged={(_, data) => {
          const last = data.after.at(-1);
          if (last) {
            balanceRef.current = last;
          }
        }}
      />
    </FullScreen>
  );
};

export default BelongFinancial;
